package com.prj.ufdm.demo.tutorial.thread;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
 * 通过显式锁使用，实现多窗口售票示例
 * Synchronized是依赖于JVM实现的，而ReenTrantLock是JDK实现的
 * ReenTrantLock的实现是一种自旋锁，通过循环调用CAS操作来实现加锁。它的性能比较好也是因为避免了使线程进入内核态的阻塞状态。
 * ReenTrantLock可以指定是公平锁还是非公平锁。而synchronized只能是非公平锁。所谓的公平锁就是先等待的线程先获得锁
 * ReenTrantLock提供了一个Condition（条件）类，用来实现分组唤醒需要唤醒的线程们，而不是像synchronized要么随机唤醒一个线程要么唤醒全部线程
 * ReenTrantLock提供了一种能够中断等待锁的线程的机制，通过lock.lockInterruptibly()来实现这个机制
 * @author Administrator
 *
 */
public class TestLock {
	
	public static void main(String[] args) {
		TLThread tlThread = new TLThread();
		new Thread(tlThread, "1号窗口").start();
		new Thread(tlThread, "2号窗口").start();
		new Thread(tlThread, "3号窗口").start();
	}

}

class TLThread implements Runnable {
	
	private int tick = 30;
	
	private Lock lock = new ReentrantLock();

	@Override
	public void run() {
		while(true){
			// 上锁
			lock.lock(); 
			try{
				if(tick > 0){
					Thread.sleep(200);
					System.out.println(Thread.currentThread().getName() + " 完成售票，余票为：" + --tick);
				}
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			// 使用显式锁，一定要用 finally 释放锁
			finally{
				lock.unlock(); 
			}
		}
	}
}